<script setup lang="ts">
/* ---- */
const stamp = {
  width: 160,
  height: 160,
  spacing: 3,
  // ----
  name: '',
  info: '',
  // ----
  callback: ''
}

/* ---- */
const open = (opt) => {
  if (opt) {
    for (var key in opt) { stamp[key] = opt[key] }
  }
  setTimeout(() => { generateStampImage() }, 300)
}
// ----
const generateStampImage = () => {
  const stampText = stamp.name
  const stampInfo = stamp.info
  // ----
  const canvasDOM = document.createElement('canvas')
  canvasDOM.width = stamp.width
  canvasDOM.height = stamp.height
  // ----
  const ctx = canvasDOM.getContext('2d')

  // --绘制圆形边框--
  ctx.beginPath()
  ctx.arc(80, 80, 75, 0, 2 * Math.PI, false)
  ctx.fillStyle = 'rgba(255, 255, 255, 0)'
  ctx.fill()
  ctx.lineWidth = 3
  ctx.strokeStyle = 'red'
  ctx.stroke()

  // --绘制五角星，并适当调整五角星大小--
  drawStar(ctx, 80, 80, 5, 30, 15)
  ctx.fillStyle = 'red'
  ctx.fill()

  // --绘制弧形文本，并调整文本的起始角度--
  if (Number(stampText.length) > 0) drawCircularText(ctx, stampText, 80, 80, 60, 'red')

  // --绘制简短说明，并显示在五角星下方--
  if (Number(stampInfo.length) > 0) {
    ctx.font = '14px Arial'
    ctx.fillStyle = 'red'
    ctx.textAlign = 'center'
    ctx.fillText(stampInfo, 80, 125)
  }

  // --绘制完毕输出图章--
  const stampImage = canvasDOM.toDataURL('image/png', 1.0)
  stamp.callback && stamp.callback(stampImage)
}
const drawStar = (ctx, cx, cy, spikes, outerRadius, innerRadius) => {
  let rot = (Math.PI / 2) * 3
  let x = cx
  let y = cy
  const step = Math.PI / spikes

  ctx.beginPath()
  ctx.moveTo(cx, cy - outerRadius)
  for (let i = 0; i < spikes; i++) {
    x = cx + Math.cos(rot) * outerRadius
    y = cy + Math.sin(rot) * outerRadius
    ctx.lineTo(x, y)
    rot += step

    x = cx + Math.cos(rot) * innerRadius
    y = cy + Math.sin(rot) * innerRadius
    ctx.lineTo(x, y)
    rot += step
  }
  ctx.lineTo(cx, cy - outerRadius)
  ctx.closePath()
}
const drawCircularText = (ctx, text, x, y, radius, color) => {
  ctx.fillStyle = color
  ctx.font = '16px Arial'
  ctx.textBaseline = 'middle'

  let startAngle = -Math.PI    // 开始于水平左侧
  let totalAngle = 0           // 计算总角度

  // --计算文本占据的总角度--
  for (let i = 0; i < text.length; i++) {
    totalAngle += (ctx.measureText(text[i]).width + stamp.spacing) / radius
  }

  // --调整开始角度，使文本居中--
  startAngle += (Math.PI - totalAngle) / 2

  for (let i = 0; i < text.length; i++) {
    const char = text[i]
    const charWidth = ctx.measureText(char).width + stamp.spacing
    const angle = startAngle + charWidth / (2 * radius)

    ctx.save()
    ctx.translate(x + Math.cos(angle) * radius, y + Math.sin(angle) * radius)
    ctx.rotate(angle + Math.PI / 2)
    ctx.fillText(char, -charWidth / 2, 0)
    ctx.restore()

    startAngle += charWidth / radius
  }
}

/* ---- */
defineExpose({
  open
})
</script>

<template></template>